#include "StompedReality/Core/TypeSystem/TypeSystem.h"
#include "StompedReality/Math/Matrix.h"
#include "StompedReality/Math/Vector2.h"

CreateRegDummy( Vector2 )

StompedReality::Math::Vector2::Vector2( )
{
  this->m_X = 0;
  this->m_Y = 0;
}

StompedReality::Math::Vector2::Vector2 ( float x, float y )
{
  this->m_X = x;
  this->m_Y = y;
}

StompedReality::Math::Vector2::~Vector2( )
{
}

const float StompedReality::Math::Vector2::GetX( ) const
{
  return this->m_X;
}

void StompedReality::Math::Vector2::SetX ( float x )
{
  this->m_X = x;
}

const float StompedReality::Math::Vector2::GetY( )  const
{
  return this->m_Y;
}

void StompedReality::Math::Vector2::SetY ( float y )
{
  this->m_Y = y;
}

StompedReality::Math::Vector2& StompedReality::Math::Vector2::operator= ( const Vector2& other )
{
  this->m_X = other.m_X;
  this->m_Y = other.m_Y;
  return *this;
}

StompedReality::Math::Vector2& StompedReality::Math::Vector2::operator+= ( const Vector2& other )
{
  this->m_X += other.m_X;
  this->m_Y += other.m_Y;
  return *this;
}

StompedReality::Math::Vector2& StompedReality::Math::Vector2::operator-= ( const Vector2& other )
{
  this->m_X -= other.m_X;
  this->m_Y -= other.m_Y;
  return *this;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator+ ( const Vector2& other )
{
  Vector2 r = *this;
  r.m_X += other.m_X;
  r.m_Y += other.m_Y;
  return r;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator- ( const Vector2& other )
{
  Vector2 r = *this;
  r.m_X -= other.m_X;
  r.m_Y -= other.m_Y;
  return r;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator* ( const float& other )
{
  Vector2 r = *this;
  r.m_X *= other;
  r.m_Y *= other;
  return r;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator*= ( const float& other )
{
  this->m_X *= other;
  this->m_Y *= other;
  return *this;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator/ ( const float& other )
{
  Vector2 r = *this;
  r.m_X /= other;
  r.m_Y /= other;
  return r;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator/= ( const float& other )
{
  this->m_X /= other;
  this->m_Y /= other;
  return *this;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator* ( StompedReality::Math::Matrix& other )
{
  Vector2 r = *this;
  float x = r.m_X;
  float y = r.m_Y;
  r.m_X = other.M( ) [0] * x + other.M( ) [1] * y + 1 * other.M( ) [3];
  r.m_Y = other.M( ) [4] * x + other.M( ) [5] * y + 1 * other.M( ) [7];
  return r;
}

StompedReality::Math::Vector2 StompedReality::Math::Vector2::operator*= ( StompedReality::Math::Matrix& other )
{
  float x = this->m_X;
  float y = this->m_Y;
  this->m_X = other.M( ) [0] * x + other.M( ) [1] * y + 1 * other.M( ) [3];
  this->m_Y = other.M( ) [4] * x + other.M( ) [5] * y + 1 * other.M( ) [7];
  return *this;
}

void StompedReality::Math::Vector2::Add ( float x, float y )
{
  this->m_X += x;
  this->m_Y += y;
}

void StompedReality::Math::Vector2::Add ( Vector2* other )
{
  this->m_X += other->m_X;
  this->m_Y += other->m_Y;
}

const float StompedReality::Math::Vector2::Dot ( const Vector2& other )
{
  return this->m_X * other.m_X + this->m_Y * other.m_Y;
}

void StompedReality::Math::Vector2::Scale ( const Vector2& other )
{
  this->m_X *= other.m_X;
  this->m_Y *= other.m_Y;
}

void StompedReality::Math::Vector2::Normalize( )
{
  float len = this->Length( );
  if ( len != 0 )
  {
    this->m_X /= len;
    this->m_Y /= len;
  }
}

const float StompedReality::Math::Vector2::Length( )
{
  return sqrt ( this->m_X * this->m_X + this->m_Y * this->m_Y );
}

bool StompedReality::Math::Vector2::Equals( const Vector2& other, float epsilon )
{
  return std::abs( this->m_X - other.m_X ) <= epsilon && std::abs( this->m_Y - other.m_Y ) <= epsilon;
}

int StompedReality::Math::Vector2Reg::registeType( )
{
  return ( int ) ( StompedReality::type_system::TypeSystem::CreateTypeInfo<Vector2> ( "Vector2" )->
                   addTypeField ( StompedReality::type_system::TypeField ( "x", &Vector2::m_X ) )->
                   addTypeField ( StompedReality::type_system::TypeField ( "y", &Vector2::m_Y ) ) );
}

static int typeReg = StompedReality::Math::Vector2Reg::registeType( );
